﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;

namespace Common.Utilities.TextMatch
{
    /// <summary>
    /// word normalization is confined to regularizing grammatical variants 
    /// such as singular/plural and present/past, the process is 
    /// called "Inflectional Stemming". 
    /// </summary>
    public class InflectionalStemmer : IWordStemmer
    {
        #region fields

        private static readonly char[] DoublingConsonants =
            new char[]
                {
                    'b',
                    'd',
                    'g',
                    'k',
                    'm',
                    'n',
                    'p',
                    'r',
                    'l',
                    't'
                };

        #endregion

        #region IWordStemmer Members

        public string StemTerm(string s)
        {
            if (string.IsNullOrEmpty(s))
                return s;

            if (s.Length < 4)
                return s;

            if (this.IsNumber(s))
                return s;

            if (this.IsAcronym(s))
                return s;

            if (s.EndsWith("s'"))
                return s.Substring(0, s.Length - 1);
            if (s.EndsWith("'s"))
                return s.Substring(0, s.Length - 2);
            if (s.EndsWith("is"))
                return s;
            if (s.EndsWith("us"))
                return s;
            if (s.EndsWith("ss"))
                return s;

            if (s.EndsWith("s"))
            {
                if (this.ExistInDictionary(s.Substring(0, s.Length - 1)))
                {
                    return s.Substring(0, s.Length - 1);
                }

            }
            if (s.EndsWith("es"))
            {
                if (this.ExistInDictionary(s.Substring(0, s.Length - 2)))
                {
                    return s.Substring(0, s.Length - 2);
                }

            }
            if (s.EndsWith("ies"))
            {
                if (this.ExistInDictionary(s.Substring(0, s.Length - 3) + "y"))
                {
                    return s.Substring(0, s.Length - 3) + "y";
                }

            }
            if (s.EndsWith("s"))
            {
                return s;
            }

            if ((!s.EndsWith("ed")) && (!s.EndsWith("ing")))
            {
                return s;
            }
            if (s.EndsWith("ed"))
            {
                if (this.ExistInDictionary(s.Substring(0, s.Length - 2)))
                {
                    return s.Substring(0, s.Length - 2);
                }

            }
            if (s.EndsWith("ied"))
            {
                return s.Substring(0, s.Length - 3) + "y";
            }
            if (s.EndsWith("eed"))
            {
                return s.Substring(0, s.Length - 1);
            }
            if (s.EndsWith("ing") && s.Length > 5)
            {
                if (this.ExistInDictionary(s.Substring(0, s.Length - 3)))
                {
                    return s.Substring(0, s.Length - 3);
                }

            }
            if (s.EndsWith("ing") && s.Length <= 5)
            {
                return s;
            }


            if (this.EndsInDoubleConsonant(s))
            {
                s = s.Substring(0, s.Length - 1);
                if (this.ExistInDictionary(s))
                {
                    return s;
                }
                if (s.EndsWith("l"))
                    return s;
                if (s.EndsWith("c") || s.EndsWith("z") && s.Length > 2)
                {
                    char secondLast = s[s.Length - 2];
                    if (secondLast == 'g' || secondLast == 'l')
                    {
                        return s + "e";
                    }
                }
                if (s.Length > 2)
                {
                    char secondLast = s[s.Length - 2];
                    if (secondLast == 'a' || secondLast == 'e' || secondLast == 'i' ||
                        secondLast == 'o' || secondLast == 'u')
                    {
                        return s + "e";
                    }
                }

                return s;
            }
            else
            {
                return s + "e";
            }
        }


        #endregion

        #region util
        private bool IsNumber(string s)
        {
            if ((!string.IsNullOrEmpty(s)) && s.Length > 0 && Regex.IsMatch(s, "^[+-]?\\d*\\.?\\d*$"))
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        private bool IsAcronym(string s)
        {
            if (!string.IsNullOrEmpty(s) && s.Length >= 2)
            {
                char[] chars = s.ToCharArray();
                foreach (char chr in chars)
                {
                    if (char.IsLower(chr))
                        return false;
                }
                return true;
            }
            else
            {
                return false;
            }
        }

        private bool EndsInDoubleConsonant(string s)
        {
            foreach (char dblConsonant in DoublingConsonants)
            {
                if (s.EndsWith(dblConsonant.ToString() + dblConsonant.ToString()))
                    return true;
            }
            return false;
        }

        private bool ExistInDictionary(string s)
        {
            // TODO: needs to load wrod net in memory
            return true;
        }
        #endregion
    }
}
